#include "stdafx.h"
#include "FPSController.h"
#include <MMSystem.h>
#include "MemTrack.h"

#pragma comment(lib, "winmm.lib")

namespace bs
{
	FpsController::FpsController()
	{
		this->curTime = 0;
		this->lastTime = 0;
		this->startTime = 0;
		this->timeCntBegin = 0;

		this->curFrame = 0;
		this->frameCntBegin = 0;

		this->curFps = 0;
		this->destFps = 0;

		this->timer = ::CreateWaitableTimer(NULL, FALSE, NULL);

		this->state = STOPED;

		::timeBeginPeriod(1);
	}

	FpsController::~FpsController()
	{
		this->Stop();

		if(this->timer)
		{
			::CloseHandle(this->timer);
			this->timer = NULL;
		}

		::timeEndPeriod(1);
	}

	void FpsController::SetDestFps(int fps)
	{
		if(!this->IsStoped())
			return;

		this->destFps = fps;
	}

	size_t FpsController::Process()
	{
		if(!this->IsRunning())
			return this->curTime;

		if(this->destFps)
		{
			::WaitForSingleObject(this->timer, INFINITE);
		}
		else
		{
			::Sleep(1);
		}
		
		++ this->curFrame;
		this->lastTime = this->curTime;
		this->curTime = ::timeGetTime() - this->startTime;

		if(this->curTime-this->timeCntBegin >= 1000)
		{
			this->curFps = (int)(this->curFrame-this->frameCntBegin) * 1000 / (int)(this->curTime-this->timeCntBegin);

			this->timeCntBegin = this->curTime;
			this->frameCntBegin = this->curFrame;

#ifdef _LOG_FPS
			SimpleLogger::Instance().Log(SimpleLogger::LL_DEBUG, "FPS: %d", this->curFps);
#endif
		}

		return this->curTime;
	}

	bool FpsController::Start()
	{
		if(!this->IsStoped())
			return true;

		this->curTime = 0;
		this->lastTime = 0;
		this->startTime = ::timeGetTime();
		this->timeCntBegin = 0;

		this->curFrame = 0;
		this->frameCntBegin = 0;

		this->curFps = this->destFps;

		if(this->timer && this->destFps)
		{
			LARGE_INTEGER li;
			::ZeroMemory(&li, sizeof(LARGE_INTEGER));
			
			if(::SetWaitableTimer(this->timer, &li, 1000/this->destFps, NULL, NULL, FALSE) != FALSE)
			{
				this->state = RUNNING;
			}
		}
		else
		{
			this->state = RUNNING;
		}

		return this->IsRunning();
	}

	void FpsController::Stop()
	{
		if(this->IsStoped())
			return;

		this->state = STOPED;

		if(this->timer)
		{
			::CancelWaitableTimer(this->timer);
		}
	}

	void FpsController::Pause()
	{
		if(this->IsStoped() || this->IsPaused())
			return;

		this->state = PAUSED;
	}

	void FpsController::Resume()
	{
		if(!this->IsPaused())
			return;

		this->state = RUNNING;

		this->startTime += ::timeGetTime() - this->curTime;
	}

}
